﻿<html>
  <head>
    <title>TIScript 3.2操作指南——类和名称空间</title>
    <link rel="stylesheet" href="for-screen.css"/>
    <meta name="generator" content="h-smile:richtext"/>
  </head>
<body>
  <h1>函数、类和名称空间的装饰器</h1>
  <div class="level1">
    <h2><a id="introduction" name="introduction">简介</a></h2>
    <div class="level2">
      <p>装饰器 <sup><a class="fn_top" id="fnt__1" href="#fn__1" name="fnt__1">1)</a></sup>是一个元编程特征。一个装饰器是一个函数，它用于修改另一个函数或方法。通常，装饰器函数创建另一个函数封装(装饰)原始的函数调用，以便做一些预先或扫尾处理。</p>
      <p>在TIScript中, 装饰器是一个普通函数，它接受一个后多个参数。第一个参数总是要装饰的对象(函数、类或名称空间)的引用。装饰器的函数名称应该以<code>@</code>字符开头。</p>
      <p>这里是一个<code>@returns</code>装饰器的示例。这个装饰器创建一个代理函数，它校验被装饰函数的返回值是否符合预期:</p>
      <pre class="code tiscript">function @returns(func, return_type)
{
  return function(params..) // 'func'的return代理函数。
  {
    var rv = func.apply(this, params); // 调用'func'函数
    if( typeof rv != return_type )     // 校验它的返回值类型
      throw String.printf(&quot;Function %s expected to return %s but got %s&quot;,
                           func.name, return_type, typeof rv);
    return rv;
  }
}
</pre>
      <p>当某函数使用了该装饰器，它能确保该函数的返回值是预期的类型:</p>
      <pre class="code tiscript">@returns #integer
function SumInt(a, b)
{
  return a + b;
}
</pre></div>
    <h2><a id="syntax-of-decorator-invocation" name="syntax-of-decorator-invocation">装饰器的调用语法</a></h2>
    <div class="level2">
      <p>TIScript的核心语法已经支持为函数和方法添加装饰器。要添加装饰器，语法类似下面:</p>
      <pre class="code">[&lt;装饰器-列表&gt;] <code>function</code> &lt;函数名&gt; <code>(</code> &lt;参数&gt; <code>)</code> <code>{</code> &lt;函数体&gt; <code>}</code> -- 命名函数;
[&lt;装饰器-列表&gt;] <code>:</code> &lt;参数&gt; <code>:</code> &lt;语句&gt; -- 匿名语句;
[&lt;装饰器-列表&gt;] <code>:</code> &lt;参数&gt; <code>{</code> &lt;函数体&gt; <code>}</code> -- 匿名函数。
</pre>
      <p>其中，<em>装饰器-列表</em>是一个或多个装饰器调用列表。每个装饰器调用由一个装饰器函数的名称(以'@'开头)和一个可选的供装饰器调用的以空格分隔参数值列表组成。</p>
      <pre class="code">@装饰器名称 [p1 [p2 [... pN ]]] &lt;函数或匿名声明&gt;
</pre></div>
    <h3><a id="empty-decorator" name="empty-decorator">空装饰器</a></h3>
    <div class="level3">
      <p>有时，你可能需要使用一个空装饰器，如创建一些函数而不是装饰另一个函数时。装饰器末尾以<code>;</code>(分号)结尾:</p>
      <pre class="code">@装饰器名 [p1 [p2 [... pN ]]] ;
</pre></div>
    <h2><a id="the-decorator-function" name="the-decorator-function">装饰器函数</a></h2>
    <div class="level2">
      <p>若一个函数被当做装饰器使用，则它的函数名称必须以<code>@</code>字符开头。</p>
      <p>装饰器函数必须至少有一个参数。这个参数将是被装饰对象的引用。</p>
      <p>装饰器函数是一个普通函数，即它可以被当做普通函数那样使用。</p></div>
    <h3><a id="this" name="this">this</a></h3>
    <div class="level3">
      <p>在装饰器中，<em>this</em>环境变量是装饰器被应用处的当前名称空间/类。如果装饰器被应用在一个全局函数，则<em>this</em>是全局名称空间对象的引用。</p>
      <h2>装饰器使用示例</h2>
      <p>这里是ScIDE源代码的一个片段:</p>
      <pre>@key 'N' @CTRL @NOSHIFT @NOALT : { openFile(); return true; } // Ctrl+N
@key 'S' @CTRL @SHIFT @NOALT : { saveAllDocuments(); return true; } // Ctrl+Shift+S
</pre>
      <p>这两行代码为self.onKey事件(见下面的<code>function @key()</code>声明)添加事件处理器(右边的匿名方法)。@CTRL、@SHIFT和@NOALT也是装饰器，它们为调用链上的事件处理器代码末尾添加自己的过滤表达式。</p>
      <p>这里说明这些装饰器是如何实现的:</p>
      <pre>// '@key'装饰器 - 根据keyCode和ctrl, shift, alt标志过滤Event.KEY_DOWN事件
// 在onKey中建立事件处理器链
function <code>@key</code>(func, keyCode = undefined, modifiers..)
{
  function t(evt)
  {
    var r = false;
    if( evt.type == Event.KEY_DOWN &amp;&amp;
        (keyCode === undefined || (keyCode == evt.keyCode)) )
          r = func.call(this,evt);
    if(t.next) return t.next.call(this,evt) || r;
    return r;
  }
  // 注意，在装饰器中的'this'是当前名称空间 - 类 或 全局(ns)
  var principal = this instanceof Behavior ? this : self;
  t.next = principal.onKey;
  principal.onKey = t;
}

// '@CTRL'装饰器 - 如果 evt.ctrlKey === true则通过
function <code>@CTRL</code>(func) { return function(evt) { if( evt.ctrlKey === true ) return func.call(this,evt); } }
// '@NOCTRL'装饰器 - 如果 evt.ctrlKey === false则通过
function <code>@NOCTRL</code>(func) { return function(evt) { if( evt.ctrlKey === false ) return func.call(this,evt); } }
</pre>
      <hr/></div>
    <div class="footnotes">
      <div><sup><a class="fn_bot" id="fn__1" href="#fnt__1" name="fn__1">1)</a></sup>TIScript中的装饰器参考了<a class="urlextern" title="http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators" href="http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators" rel="nofollow">Python中的装饰器</a> 编程语言。</div></div></div>
</body>
</html>
